#pragma once

#include "Socket.hpp"
#include <jsoncpp/json/json.h>
#include <iostream>
#include <string>
#include <memory>
#include <functional>

// 自定义协议
// 实现序列化和反序列化
// 解决是否可以拿到完整数据包的问题
using namespace SocketModule;

// 请求报文
// client->server
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper)
        : _x(x), _y(y), _oper(oper)
    {
    }
    // 序列化
    std::string Serialize()
    {
        Json::Value root;
        root["x"]=_x;
        root["y"]=_y;
        root["oper"]=_oper;

        Json::FastWriter writer;
        std::string s=writer.write(root);
        return s;
    }
    // 反序列化
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok=reader.parse(in,root);
        if(ok)
        {
            _x=root["x"].asInt();
            _y=root["y"].asInt();
            _oper=root["oper"].asInt();
        }
        return ok;
    }
    int X(){return _x;}
    int Y(){return _y;}
    char Oper(){return _oper;}
private:
    int _x;
    int _y;
    char _oper;
};

// 应答报文
// serevr->client
class Response
{
public:
    Response()
    {
    }
    Response(int result, int code)
        : _result(result),
          _code(code)
    {
    }
    // 序列化
    std::string Serialize()
    {
        Json::Value root;
        Json::FastWriter writer;
        root["result"]=_result;
        root["code"]=_code;

        std::string s=writer.write(root);
        return s;
    }
    // 反序列化
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok=reader.parse(in,root);
        if(ok)
        {
            _result=root["result"].asInt();
            _code=root["code"].asInt();
        }
        return ok;
    }
    int Result(){return _result;}
    int Code(){return _code;}
    void Setresult(int x)
    {
        _result=x;
    }
    void Setcode(int x)
    {
        _code=x;
    }
    void show()
    {
        std::cout<<"计算结果是："<<_result<<"["<<_code<<"]"<<std::endl;
    }
private:
    int _result;
    int _code; // 运算是否合法，0表示合法
};

const std::string grep="\r\n";
using func_t=std::function<Response(Request&)>;
// 协议
// 保证读取的时候，读取到正确的请求报文和应答报文
class Protocol
{
public:
    Protocol(func_t func)
    :_func(func)
    {}
    Protocol()
    {
        
    }
    //封装报头
    std::string Encode(const std::string& jsonstr)
    {
        int len=jsonstr.size();
        std::string len_str=std::to_string(len);
        return len_str+grep+jsonstr+grep; //异常出现所在
    }
    //解析报文
    //以输出型参数的形式将结果带回
    bool Decode(std::string& buffer,std::string* package)
    {
        //首先查找buffer中是否存在grep
        ssize_t pos=buffer.find(grep);
        if(pos==std::string::npos)
        return false;//不可能包含完整的数据报

        //走到这里说明存在数据报，但不一定包含完整的数据报
        //可能包含半个数据报，可能只包含一个数据报，也可能包含多个数据报
        //如果包含半个数据报，则返回继续从缓冲区中读取
        //如果包含一个 或者多个或者多个半数据报，提取出来一个完整的数据报
        //以输出型参数的形式返回带出，并从缓冲区中删除该部分 
        //检查数据包的长度是否满足要求
        std::string len_str=buffer.substr(0,pos);
        int len_int=std::stoi(len_str);//异常？？

        int target_len=2*grep.size()+len_str.size()+len_int;//一个完整数据包的大小
        if(buffer.size()<target_len)  //不包含一个完整的数据报，继续读取
        return false;

        //走到这里说明buffer中包含一个或者多个数据包
        //截取出一个完整的数据包
        *package=buffer.substr(pos+grep.size(),len_int);
        buffer.erase(0,target_len);
        return true;
    }

    //获取请求
    //发送应答
    void GetRequest(std::shared_ptr<Socket>& sock,InetAddr& client)
    {
        //需要读取方法
        //从网络中获取write和send
        //需要网络套接字和客户端信息
        //这些在为网络模块中通过回调的方式调用
        std::string buffer_queue;
        while(true)
        {
            int n=sock->Recv(&buffer_queue);
            if(n>0)
            {
                //1.解析报文
                std::string json_package;
                bool ret=Decode(buffer_queue,&json_package);
                if(ret==false)
                continue;

                //2,得到一个json串{..................}
                //定义请求对象，反序列化，填充对象的成员变量
                Request req;
                bool ok=req.Deserialize(json_package);
                if(ok==false)
                continue;

                //3,得到了请求对象，保安和你两个操作数和一个操作符
                //需要完成计算任务——再封装成一个模块
                //采用回调的方式执行计算的模块
                //传给一个Request请求，返回一个 Ressponse应答
                Response resp=_func(req);

                //4，拿到了结果需要给客户端发送过去
                //4.1,首先进行序列化
                std::string json_str=resp.Serialize();

                //4.2,封装报头，添加自定义长度
                std::string end_str=Encode(json_str);

                //4.3,发送给客户端
                sock->Send(end_str);
            }
        }
    }
    //获取应答
    bool GetResponse(std::shared_ptr<Socket> &client,std::string& resp_buffer,Response* resp)
    {
        while(true)
        {
            int n=client->Recv(&resp_buffer);
            if(n>0)
            {
                std::string json_package;
                while(Decode(resp_buffer,&json_package))
                {
                    resp->Deserialize(json_package);
                }
                return true;
            }
            else if (n == 0)
            {
                std::cout << "server quit " << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }
    //构建一个请求 
    std::string BuildRequest(int x,int y,char oper)
    {
        Request req(x,y,oper);
        //序列化
        std::string json_req=req.Serialize();
        //添加报头
        return Encode(json_req);
    }
private:
    func_t _func;
};